package com.goldsprite.gameframeworks.ecs.component;

import com.goldsprite.gameframeworks.ecs.LayerMask;
import com.goldsprite.gameframeworks.log.Debug;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import com.goldsprite.gameframeworks.input.*;
import com.goldsprite.gameframeworks.utils.StringUtils;
import com.goldsprite.gameframeworks.utils.math.Vector2;

public abstract class ColliderComponent<T> extends Component implements PhysicsEventListener {
	public RigidbodyComponent rigi;
	protected final Vector2 offset = new Vector2(0, 0);
	private final Vector2 worldPosition = new Vector2();
	protected String layerName;
	protected boolean isTrigger;
	protected short categoryBits;
	protected short maskBits;

	List<ColliderComponent> stayTriggerColliders = new ArrayList<>();
	List<ColliderComponent> stayCollisionColliders = new ArrayList<>();

	public final Event<ColliderComponent> onTriggerEnterEvent = new Event<>();
	public final Event<ColliderComponent> onTriggerExitEvent = new Event<>();

	public ColliderComponent() {
		setLayerName("Default");
	}

	@Override
	public void awake() {
		rigi = getComponent(RigidbodyComponent.class);
		if (rigi == null) throw new RuntimeException(StringUtils.formatString("%s需要前置组件: %s", getClass().getSimpleName(), RigidbodyComponent.class.getSimpleName()));
		rigi.attachCollider(this);

		super.awake();
	}

	public Vector2 getWorldPosition() {
		return worldPosition.set(offset).scl(getTransform().getFace()).add(rigi.getPosition());
	}

	public Vector2 getWorldRenderPosition() {
		return worldPosition.set(offset).scl(getTransform().getFace()).add(getTransform().getPosition());
	}

	public boolean isTrigger() {
		return isTrigger;
	}

	public void setTrigger(boolean trigger) {
		this.isTrigger = trigger;
	}

	@Override
	public void destroy() {
		super.destroy();
		rigi.detachCollider(this);
	}

	// PhysicsEventListener 接口实现
	@Override
	public void onTriggerEnter(ColliderComponent other, FullCollisionResult result) {
		Debug.logT("PhysicsCallback", "%s-%s触发器进入: 物体-%s", getGObject().getName(), getName(), other.getGObject().getName());
		if(!stayTriggerColliders.contains(other)){
			stayTriggerColliders.add(other);
			Debug.log("stayTriggerColliders变更: 当前%s个", stayTriggerColliders.size());
		}
		// 子类可重写
		onTriggerEnterEvent.invoke(other);
	}

	@Override
	public void onTriggerExit(ColliderComponent other, FullCollisionResult result) {
		Debug.logT("PhysicsCallback", "%s-%s触发器退出: 物体-%s", getGObject().getName(), getName(), other.getGObject().getName());
		if(stayTriggerColliders.contains(other)){
			stayTriggerColliders.remove(other);
			Debug.log("stayTriggerColliders变更: 当前%s个", stayTriggerColliders.size());
		}
		// 子类可重写
		onTriggerExitEvent.invoke(other);
	}

	@Override
	public void onCollisionEnter(ColliderComponent other, FullCollisionResult result) {
		Debug.logT("PhysicsCallback", "%s-%s碰撞器进入: 物体-%s", getGObject().getName(), getName(), other.getGObject().getName());
		if(!stayCollisionColliders.contains(other)){
			stayCollisionColliders.add(other);
			Debug.log("stayCollisionColliders变更: 当前%s个", stayCollisionColliders.size());
		}
		// 子类可重写
	}

	@Override
	public void onCollisionExit(ColliderComponent other, FullCollisionResult result) {
		Debug.logT("PhysicsCallback", "%s-%s碰撞器退出: 物体-%s", getGObject().getName(), getName(), other.getGObject().getName());
		if(stayCollisionColliders.contains(other)){
			stayCollisionColliders.remove(other);
			Debug.log("stayCollisionColliders变更: 当前%s个", stayCollisionColliders.size());
		}
		// 子类可重写
	}

	public List<ColliderComponent> getStayTriggerColliders() {
		return stayTriggerColliders;
	}
	public List<ColliderComponent> getStayCollisionColliders() {
		return stayCollisionColliders;
	}


	public int getLayer() {
		return LayerMask.nameToLayer(layerName);
	}

	public String getLayerName() {
		return layerName;
	}

	public void setLayerName(String layerName) {
		this.layerName = layerName;
	}

	public boolean canCollideWith(String layerName) {
		short layerBit = LayerMask.nameToCategoryBits(layerName);
		return (this.maskBits & layerBit) != 0;
	}

	// 获取当前碰撞的层名称列表（用于调试）
	public List<String> getCollidingLayers() {
		List<String> layers = new ArrayList<>();
		BitSet currentMask = LayerMask.maskBitsToBitSet(this.maskBits);

		for (String layer : LayerMask.getAllLayers()) {
			int layerIndex = LayerMask.nameToLayer(layer);
			if (currentMask.get(layerIndex)) {
				layers.add(layer);
			}
		}
		return layers;
	}

	public Vector2 getOffset() {
		return offset;
	}
	public void setOffset(float x, float y) {
		this.offset.set(x, y);
	}

	public boolean isCollision() {
		return !stayCollisionColliders.isEmpty();
	}
	public boolean isCollision(String tag) {
		boolean hasTagColl = false;
		for(ColliderComponent coll : getStayCollisionColliders()){
			if(tag.equals(coll.getTag())){
				hasTagColl = true;
				break;
			}
		}
		return hasTagColl;
	}

	public abstract ShapeType getShapeType();

	public abstract T getShape();
}
